using System;
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace WPFTemplateLib.Attached
{
	/// <summary>
	/// 多选控件（附加属性）帮助类
	/// </summary>
	/// <example>
	///	<![CDATA[
	///	lib:MultiSelectorHelper.MonitorSelectionChanged="True"
	///	lib:MultiSelectorHelper.BindableSelectedItems="{Binding SelectedItemsForAttached, Mode=OneWayToSource}"
	/// ]]>
	/// </example>
	public class MultiSelectorHelper
	{
		#region 多选项集合绑定

		//来自：《[WPF 中如何将多选项目的 SelectedItems 属性绑定到 ViewModel](https://www.bilibili.com/video/BV1HM411k76b/)》
		//https://gist.github.com/BYJRK/33932133a6fc1951d3a935b8f30b2d79

		#region Bindable SelectedItems
		public static IList GetBindableSelectedItems(DependencyObject obj)
		{
			return (IList)obj.GetValue(BindableSelectedItemsProperty);
		}
		/// <summary>
		/// [附加属性] 可绑定的选中项(多选)集合
		/// </summary>
		public static void SetBindableSelectedItems(DependencyObject obj, IList value)
		{
			obj.SetValue(BindableSelectedItemsProperty, value);
		}

		public static readonly DependencyProperty BindableSelectedItemsProperty =
			DependencyProperty.RegisterAttached("BindableSelectedItems", typeof(IList), typeof(MultiSelectorHelper), new PropertyMetadata(null));
		#endregion

		#region Monitor SelectionChanged
		public static bool GetMonitorSelectionChanged(DependencyObject obj)
		{
			return (bool)obj.GetValue(MonitorSelectionChangedProperty);
		}
		/// <summary>
		/// [附加属性] 是否监控选择改变事件（监控则赋值 BindableSelectedItems）
		/// </summary>
		public static void SetMonitorSelectionChanged(DependencyObject obj, bool value)
		{
			obj.SetValue(MonitorSelectionChangedProperty, value);
		}

		public static readonly DependencyProperty MonitorSelectionChangedProperty =
			DependencyProperty.RegisterAttached("MonitorSelectionChanged", typeof(bool), typeof(MultiSelectorHelper),
				new PropertyMetadata(false, MonitorSelectionChangedPropertyChangedCallback));

		private static void MonitorSelectionChangedPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			if(d is not MultiSelector selector)
				throw new InvalidOperationException();

			if((bool)e.NewValue)
				selector.SelectionChanged += OnSelectionChanged;
			else
				selector.SelectionChanged -= OnSelectionChanged;
		}

		private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			var selector = (MultiSelector)sender;
			SetBindableSelectedItems(selector, selector.SelectedItems);
			selector.GetBindingExpression(BindableSelectedItemsProperty)?.UpdateSource();
		}
		#endregion 

		#endregion
	}
}
